package com.zhihao.sdk.infrastructure.git;

import com.zhihao.sdk.types.utils.RandomStringUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;

public class GitCommand {

    private final Logger logger = LoggerFactory.getLogger(GitCommand.class);

    /* github review log uri(评审日志url) */
    private final String githubReviewLogUri;

    /* github token */
    private final String githubToken;

    /* github project */
    private final String project;

    /* github project branch */
    private final String branch;

    /* github project author */
    private final String author;

    /* github project message（代码提交时的信息） */
    private final String message;

    /*
     * 构造函数
     *
     * @param githubReviewLogUri
     * @param githubToken
     * @param project
     * @param branch
     * @param author
     * @param message
     */
    public GitCommand(String githubReviewLogUri, String githubToken, String project, String branch, String author, String message) {
        this.githubReviewLogUri = githubReviewLogUri;
        this.githubToken = githubToken;
        this.project = project;
        this.branch = branch;
        this.author = author;
        this.message = message;
    }

    /**
     * 获取git diff
     *
     * @return
     * @throws IOException
     * @throws InterruptedException
     */
    public String diff() throws IOException, InterruptedException {
        // 获取最新一次提交的完整哈希值（%H 表示完整哈希值），用于后续执行 git diff 命令
        ProcessBuilder logProcessBuilder = new ProcessBuilder("git", "log", "-1", "--pretty=format:%H");
        logProcessBuilder.directory(new File(".")); // 设置当前工作目录为项目根目录
        Process logProcess = logProcessBuilder.start();

        BufferedReader logReader = new BufferedReader(new InputStreamReader(logProcess.getInputStream()));
        String latestCommitHash = logReader.readLine(); // 读取最新提交的哈希值
        logReader.close();
        logProcess.waitFor(); // 等待日志进程完成

        // 使用最新提交及其父提交之间的差异来生成 diff 内容
        ProcessBuilder diffProcessBuilder = new ProcessBuilder("git", "diff", latestCommitHash + "^", latestCommitHash);
        diffProcessBuilder.directory(new File(".")); // 设置当前工作目录为项目根目录
        Process diffProcess = diffProcessBuilder.start();

        StringBuilder diffCode = new StringBuilder();
        BufferedReader diffReader = new BufferedReader(new InputStreamReader(diffProcess.getInputStream()));
        String line;
        while ((line = diffReader.readLine()) != null) { // 逐行读取 diff 输出
            diffCode.append(line).append("\n");
        }
        diffReader.close();

        int exitCode = diffProcess.waitFor(); // 等待 diff 进程完成
        if (exitCode != 0) { // 检查 diff 命令是否成功执行
            throw new RuntimeException("Failed to get diff, exit code:" + exitCode);
        }

        return diffCode.toString(); // 返回生成的 diff 内容
    }

    /**
     * 代码评审建议日志的生成和存储（由于是存储在一个github的repo，所以相当于也是将“评审日志文件”提交推送至github）
     *
     * @param recommend 代码评审建议，用于将其写入并生成 Markdown 文件
     * @return 生成的评审文件在 GitHub 上的访问 URL
     * @throws Exception 如果克隆、提交或推送过程中发生错误
     */
    public String commitAndPush(String recommend) throws Exception {
        // 克隆远程仓库到本地临时目录 "repo"
        Git git = Git.cloneRepository()
                .setURI(githubReviewLogUri + ".git")
                .setDirectory(new File("repo"))
                .setCredentialsProvider(new UsernamePasswordCredentialsProvider(githubToken, ""))
                .call();

        // 创建日期命名的文件夹，用于存储代码评审建议
        String dateFolderName = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        File dateFolder = new File("repo/" + dateFolderName);
        if (!dateFolder.exists()) {
            dateFolder.mkdirs(); // 如果文件夹不存在，则创建
        }

        // 生成唯一的文件名，包含项目信息、分支、作者和随机数字
        String fileName = project + "-" + branch + "-" + author + System.currentTimeMillis() + "-" + RandomStringUtils.randomNumeric(4) + ".md";
        File newFile = new File(dateFolder, fileName);

        // 将代码评审建议写入新生成的 Markdown 文件
        try (FileWriter writer = new FileWriter(newFile)) {
            writer.write(recommend);
        }

        // 添加新文件到暂存区
        git.add().addFilepattern(dateFolderName + "/" + fileName).call();

        // 提交更改，设置提交信息
        git.commit().setMessage("add code review new file" + fileName).call();

        // 推送提交到远程仓库
        git.push().setCredentialsProvider(new UsernamePasswordCredentialsProvider(githubToken, "")).call();

        logger.info("openai-code-review git commit and push done! {}", fileName);

        // 返回生成文件的 GitHub 访问 URL
        return githubReviewLogUri + "/blob/master/" + dateFolderName + "/" + fileName;
    }

    public String getProject() {
        return project;
    }

    public String getBranch() {
        return branch;
    }

    public String getAuthor() {
        return author;
    }

    public String getMessage() {
        return message;
    }
}
